#pragma once
#include <stdio.h>
#include <system\iobject.h>
#include <resource\metaclass.h>

namespace gecko
{

	//---------------------------------------------------------------------------------------------

	class MetaClass;
	class IStream;

	//---------------------------------------------------------------------------------------------

	// base class for serialisable objects
	class ISerialisable : public IObject
	{
	public:
		RTTI_DECL(ISerialisable)

		// serialiser the object to a stream
		void Serialise(IStream& stream, MetaClass* fileMetaClass = NULL);
		
		// this is implemented by the datamap macros below
		virtual MetaClass& GetMetaClass();;

	private:
		// set defaults on object prior to serialisation
		void ClearObjectData();
	};

	//---------------------------------------------------------------------------------------------

}

//---------------------------------------------------------------------------------------------

#define DATA_OFFSET(type,field) \
	((int) (((char*)&((type)->field)) - (char*)(type)))

//---------------------------------------------------------------------------------------------

#define BEGIN_DATAMAP(CLASSNAME, PARENTCLASS) \
	virtual gecko::MetaClass & GetMetaClass() \
	{ \
		CLASSNAME * dummy = NULL; \
		char * myClassName = #CLASSNAME; \
		static gecko::MetaClass& parentClass = PARENTCLASS::GetMetaClass(); \
		\
		static gecko::MetaClass::Member s_memberArray[] = \
		{

//---------------------------------------------------------------------------------------------

#define REGISTER_CHAR(MEMBER) \
	#MEMBER, gecko::MetaClass::Char, DATA_OFFSET(dummy, MEMBER), sizeof(char),

//---------------------------------------------------------------------------------------------

#define REGISTER_SHORT(MEMBER) \
	#MEMBER, gecko::MetaClass::Short, DATA_OFFSET(dummy, MEMBER), sizeof(short),

//---------------------------------------------------------------------------------------------

#define REGISTER_BOOL(MEMBER) \
	#MEMBER, gecko::MetaClass::Bool, DATA_OFFSET(dummy, MEMBER), sizeof(bool),

//---------------------------------------------------------------------------------------------

#define REGISTER_INT32(MEMBER) \
	#MEMBER, gecko::MetaClass::Int32, DATA_OFFSET(dummy, MEMBER), sizeof(int),

//---------------------------------------------------------------------------------------------

#define REGISTER_INT64(MEMBER) \
	#MEMBER, gecko::MetaClass::Int64, DATA_OFFSET(dummy, MEMBER), sizeof(__int64),

//---------------------------------------------------------------------------------------------

#define REGISTER_FLOAT(MEMBER) \
	#MEMBER, gecko::MetaClass::Float, DATA_OFFSET(dummy, MEMBER), sizeof(float),

//---------------------------------------------------------------------------------------------

#define REGISTER_DOUBLE(MEMBER) \
	#MEMBER, gecko::MetaClass::Double, DATA_OFFSET(dummy, MEMBER), sizeof(double),

//---------------------------------------------------------------------------------------------

#define REGISTER_STRING(MEMBER, LEN) \
	#MEMBER, gecko::MetaClass::String, DATA_OFFSET(dummy, MEMBER), LEN,

//---------------------------------------------------------------------------------------------

#define REGISTER_MATRIX44(MEMBER) \
	#MEMBER, gecko::MetaClass::Matrix44, DATA_OFFSET(dummy, MEMBER), sizeof(Matrix44),

//---------------------------------------------------------------------------------------------

#define END_DATAMAP \
		}; \
		static gecko::MetaClass myMetaClass(myClassName, s_memberArray, sizeof(s_memberArray) / sizeof(gecko::MetaClass::Member), parentClass); \
		return myMetaClass; \
	}

//---------------------------------------------------------------------------------------------

/*
virtual MetaClass & GetMetaClass()
{
	CLASSNAME * dummy = NULL;
	char * myClassName = #CLASSNAME;

	static MetaClass::Member s_memberArray[] =
	{
		#MEMBER, MetaClass::Float, DATA_OFFSET(dummy, MEMBER), sizeof(float),
		#MEMBER, MetaClass::Int32, DATA_OFFSET(dummy, MEMBER), sizeof(int),
		#MEMBER, MetaClass::Short, DATA_OFFSET(dummy, MEMBER), sizeof(short),
		#MEMBER, MetaClass::String, DATA_OFFSET(dummy, MEMBER), LEN,
	};

	static MetaClass myMetaClass(myClassName, s_memberArray, sizeof(s_memberArray) / sizeof(MetaClass::Member));
	
	return myMetaClass;
}
*/
